(function(global){    
    var _toString = Object.prototype.toString,
        _numberRegionRegexp = /^(\[|\()\d+\-\d+(\]|\))$/,
        _isType = function(type) {
            return function(v) {
                return _toString.call(v) === '[object ' + type + ']';
            };
        };
     
    var Type = {
        isObject : _isType('Object'),
        isString : _isType('String'),
        /**
         * 判断指定的字符串是否可能是一个表达式.
         * 表达式必要条件：
         * 1. 非纯字母,数字,下划线.
         * 2. 字符串中包含@或点(.).
         * 
         * 表达式格式，如:
         * @aaa
         * @@lan(ujs.component.selectBox)
         * location.href
         * 
         * @param {String} str
         */
        isExpression : function(str){
            if(str && ujs.Type.isString(str)){
                return !/^\w+$/.test(str) && ( str.indexOf('@') === 0 || str.indexOf('.') > -1 );
            } else {
                return false;
            }
        },
        isNumber : _isType('Number'),
        /**
         * 判断字符串是否是纯数字.
         */
        isStrNumber : function(str){
            return !!str.match(/^\d+$/);
        },
        /**
         * 判断字符串是否是数字区间. 如:
         * [4000-5000], (4000-5000), (4000-5000], [4000-5000)
         */
        isNumberRegion : function(str){            
            return _numberRegionRegexp.test(str);
        },
        isArray : Array.isArray || _isType('Array'),
        isFunction : _isType('Function'),
        isFile : _isType('File'),
        isRegExp : _isType('RegExp'),
        isBoolean : _isType('Boolean'),
        isUndefined : _isType('Undefined'),
        isNull : _isType('Null'),
        isJQuery : function(obj){            
            return obj && obj.constructor === window.jQuery;
        },
        isNullOrUndefined : function(v){
            return this.isNull(v) || this.isUndefined(v);
        },
        isEmpty : function(v){
            switch (typeof v){
                case 'undefined' : 
                    return true;
                case 'string'    : 
                    v = ujs.str.trim(v);
                    if(!v.length) return true; 
                    break;
                case 'boolean'   : 
                    if(!v) return true; 
                    break;
                case 'number'    : 
                    if(0 === v) return true; 
                    break;
                case 'object'    :
                    if(null === v) return true;
                    if(undefined !== v.length && v.length == 0) return true;
                    for(var k in v){return false;} 
                    return true;                    
            }
            return false;
        },
        isWindow : function(obj) {
            return obj != null && obj == obj.window;
        },
        isEmptyObject : function(obj){
            for(var key in obj){
                return false;
            }
            return true;
        }, 
        //测试对象是否是纯粹的对象（通过 "{}" 或者 "new Object" 创建的）。
        isPlainObject : function (obj) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that DOM nodes and window objects don't pass through, as well
            if (!this.isObject(obj) || obj.nodeType || this.isWindow(obj)){
                return false;
            }    
            var core_hasOwn = Object.prototype.hasOwnProperty;
            try {
                // Not own constructor property must be Object
                if ( obj.constructor &&
                    !core_hasOwn.call(obj, "constructor") &&
                    !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
                    return false;
                }
            } catch ( e ) {
                // IE8,9 Will throw exceptions on certain host objects #9897
                return false;
            }    
            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.    
            var key;
            for ( key in obj ) {}
    
            return key === undefined || core_hasOwn.call(obj, key);
        },
        /**
         * 判断指定的值是否是可枚举的.
         * @notested
         * @param v {Object},
         * @return {Boolean}
         */
        isEnumerable : function(v){
            return (v != null && typeof v.length == 'number' && _toString.call(v) != '[object Function]' );
        },
        /**
         * 转换值为整数.
         */
        toInt : function(val, defVal) {
            val = parseInt(val);
            return (isNaN(val) || !isFinite(val)) ? (defVal || 0 ) : val;
        }
    };
    
    //----------------------------------------------------------------------------------------------------------
    
    //TODO 老版本兼容性代码，新项目中去掉.
    global.Type = Type;
    
    ujs.define('Type', 'ujs', function(){
        return Type;
    });    
})(window);    